using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;


namespace Camalon.Drawing.Shapes
{
    /// <summary>
    /// Summary description for Bezier.
    /// </summary>
	[ToolboxItem(true)]
	[ToolboxBitmap( typeof(Bezier),"Bezier.bmp")]
    [Designer("Camalon.Drawing.Design.BezierDesigner, Camalon.Drawing.Design", typeof(IDesigner))]
    public class Bezier : VectorShape
	{

        /// <summary>
        /// Initializes a new instance of the <see cref="Bezier"/> class.
        /// </summary>
		public Bezier():base( Rectangle.FromLTRB(100,100,300,100))
		{
			base.SetPoints(new AnchorPoint[]{ 
												new AnchorPoint( 0,0), 
												new AnchorPoint( 100,100),
												new AnchorPoint( 200,0),
												new AnchorPoint( 300,100)	
											});

		}

        /// <summary>
        /// Makes the path based o the given points.
        /// </summary>
        /// <param name="points">The points that makes the path.</param>
        /// <param name="closed">if set to <c>true</c> the path is [closed].</param>
        /// <returns>Created GraphicsPath object</returns>
		protected override GraphicsPath MakePath(Point[] points, bool closed )
		{
			GraphicsPath path = new GraphicsPath();

			try
			{
				if( points != null && points.Length >=4) path.AddBeziers(points);
				else path.AddRectangle( base.Bounds );

				float flatness = _flatness;
				if( flatness <0.001f) flatness = 0.001f;
				path.Flatten( null, flatness);

				if( closed ) path.CloseAllFigures();
				
			}
			catch( Exception e)
			{
				FileWatcher.WriteLine( e.StackTrace);
			}

			return path;
		}


		private float _flatness = 1.0f;
        /// <summary>
        /// Gets or sets the flatness.
        /// </summary>
        /// <value>The flatness.</value>
		[Category("Style")]
		[DefaultValue(1.0f)]
		public float Flatness
		{	
			get{ return _flatness;}
			set
			{
				if( value < 0f) value = 0f;
				_flatness = value;
				InvokeInternalChanged( true );
			}

		}


		private void AddBezier( AnchorPoint p1, AnchorPoint p2, AnchorPoint p3 )
		{
				ArrayList list = new ArrayList( base.GetPoints() );
				list.AddRange(new AnchorPoint[]{ p1,p2,p3 });
				base.Points = list.ToArray( typeof( AnchorPoint)) as AnchorPoint[];
			
		}

        /// <summary>
        /// Validates the bzeir points in an array whether or not they can build make a bezier path.
        /// </summary>
        /// <param name="points">The bezier points.</param>
        /// <returns><c>true</c> if valid</returns>
		protected override bool ValidatePoints(AnchorPoint[] points)
		{
			if( points == null || points.Length < 4 ) 
				throw new InvalidOperationException("Line must contain at least (4 + 3n) points");
			
			int n = points.Length - 4;
			int rem = int.MaxValue; 
			Math.DivRem( n, 3, out rem );
			if( rem != 0 )
				throw new InvalidOperationException("Line must contain at least (4 + 3n) points");

			return true;
		}


	}
}
